﻿//-----------------------------------------------------------------------
// <copyright file="HasDisposeMethodWithFlagParameter.cs" company="None">
//     Copyright (c) 2009-2012
// </copyright>
//-----------------------------------------------------------------------

namespace CleanCode.StyleCopCustomRules.UnitTests.Resources
{
    using System;
    using System.ComponentModel;

    /// <summary>
    /// Dummy class to unit test the customized StyleCop rules.
    /// Taken from Microsoft help system.
    /// </summary>
    public class HasDisposeMethodWithFlagParameter : IDisposable
    {
        /// <summary>
        /// Pointer to an external unmanaged resource.
        /// </summary>
        private IntPtr handle;

        /// <summary>
        /// Other managed resource this class uses.
        /// </summary>
        private Component component = new Component();

        /// <summary>
        /// Track whether Dispose has been called.
        /// </summary>
        private bool disposed;

        /// <summary>
        /// Finalizes an instance of the<see cref="HasDisposeMethodWithFlagParameter"/>class.
        /// Use C# destructor syntax for finalization code.
        /// This destructor will run only if the Dispose method
        /// </summary>
        ~HasDisposeMethodWithFlagParameter()
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.
            this.Dispose(false);
        }

        /// <summary>
        /// Implement IDisposable.
        /// Do not make this method virtual.
        /// A derived class should not be able to override this method.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);

            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Dispose(bool disposing) executes in two distinct scenarios.
        /// </summary>
        /// <param name="disposing">
        /// If disposing equals true, the method has been called directly
        /// or indirectly by a user's code. Managed and unmanaged resources
        /// can be disposed.
        /// If disposing equals false, the method has been called by the
        /// runtime from inside the finalizer and you should not reference
        /// other objects. Only unmanaged resources can be disposed.
        /// </param>
        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (this.disposed == false)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if (disposing)
                {
                    // Dispose managed resources.
                    this.component.Dispose();
                }

                // Call the appropriate methods to clean up
                // unmanaged resources here.
                // If disposing is false,
                // only the following code is executed.
                CloseHandle(this.handle);
                this.handle = IntPtr.Zero;

                // Note disposing has been done.
                this.disposed = true;
            }
        }

        /// <summary>
        /// Closes an open object handle.
        /// </summary>
        /// <remarks>
        /// Use interop to call the method necessary to clean up the unmanaged resource.
        /// </remarks>
        /// <param name="handle">A valid handle to an open object.</param>
        /// <returns>
        /// If the function succeeds, the return value is nonzero.
        /// If the function fails, the return value is zero. To get extended 
        /// error information, call GetLastError.
        /// If the application is running under a debugger, the function will 
        /// throw an exception if it receives either a handle value that is 
        /// not valid or a pseudo-handle value. This can happen if you close 
        /// a handle twice, or if you call CloseHandle on a handle returned by 
        /// the FindFirstFile function instead of calling the FindClose function.
        /// </returns>
        [System.Runtime.InteropServices.DllImport("Kernel32")]
        private static extern bool CloseHandle(IntPtr handle);
    }
}
